<script setup lang="ts">
import { reactive, ref, watch, nextTick, onMounted, onBeforeUnmount } from 'vue';
import { ElMessage, type ElDrawer, type ElForm, type ElTable } from 'element-plus';
import { ArrowUp, Close, Plus, SuccessFilled } from '@element-plus/icons-vue';
import calendarIcon from '@/components/CalendarIcon.vue';
import clockIcon from '@/components/ClockIcon.vue';
import dataEmpty from '@/assets/images/data_empty.svg';
import dayjs from 'dayjs';
import * as _ from 'lodash-es';
import { useRoute, useRouter } from 'vue-router';
import Sortable from 'sortablejs';
import type { SortableEvent } from 'sortablejs';
import localForage from 'localforage';
import * as XLSX from 'xlsx';
import { name as projectName } from '@/../package.json';

// 路由实例
const route = useRoute();
// 本页面在路由上的名称
const pageTitleName = (route.meta.title as string) || '';
const router = useRouter();

// 主页面查询区表单组件
const queryAreaFormRef = ref<InstanceType<typeof ElForm>>();
// 右侧抽屉组件
const rightDrawer = ref<InstanceType<typeof ElDrawer>>();

onBeforeUnmount(() => {
  clearTimer();
});

/************************************************/
/**************** 参数配置区 开始 ****************/
/************************************************/

interface QueryFormConfigItem {
  /** 字段标签名 */
  fieldLabel: string;
  /** 字段名称 */
  fieldName: string;
  /**
   * 字段类型。
   *
   * - INPUT: 输入框 (默认)
   * - SELECT: 下拉框
   * - DATE: 日期选择器
   * - RANGE_DATE: 日期范围选择器
   * - RANGE_DATE_FREE: 日期范围选择器(无默认值)
   * - DATETIME: 日期时间选择器
   * - RANGE_DATETIME: 日期时间范围选择器
   * - RANGE_DATETIME_FREE: 日期时间范围选择器(无默认值)
   */
  fieldType?: string;
  /**
   * 字段值类型。
   *
   * - STRING: 字符串 (默认)
   * - NUMBER: 数字
   * - DATE: 日期
   * - ARRAY: 数组
   */
  valueType?: string;
  /**
   * 字段固定模式。
   *
   * - movable: 可拖动 (默认)
   * - left: 固定在左侧
   * - right: 固定在右侧
   */
  fixMode?: 'movable' | 'left' | 'right';
  /** 字段选项，当fieldType为SELECT时，需要传入该字段 */
  fieldOptions?: fieldOptionsItem[];
  /** 其他任意属性 */
  [key: string]: unknown;
}
interface fieldOptionsItem {
  label: string;
  value: string | number;
}
// 查询表单配置项
const queryFormConfigInit = ref<QueryFormConfigItem[]>([
  { fieldLabel: '司机姓名', fieldName: 'driverName', fixMode: 'left' },
  { fieldLabel: '司机手机号', fieldName: 'driverPhone', fixMode: 'left' },
  { fieldLabel: '车牌号', fieldName: 'carNumber' },
  { fieldLabel: '需求车型', fieldName: 'carType', fieldType: 'MULTI_SELECT', fieldOptions: [] },
  {
    fieldLabel: '送货地点',
    fieldName: 'deliveryAddress',
    fieldType: 'CASCADE_MULTI_SELECT',
    fieldOptions: []
  },
  {
    fieldLabel: '是否计量',
    fieldName: 'isMeasure',
    fieldType: 'SELECT',
    valueType: 'NUMBER',
    fieldOptions: [
      { label: '是', value: 1 },
      { label: '否', value: 0 }
    ]
  },
  { fieldLabel: '进厂日期', fieldName: 'inDate', fieldType: 'DATE' },
  { fieldLabel: '出厂日期', fieldName: 'outDate', fieldType: 'DATE' },
  { fieldLabel: '创建时间', fieldName: 'createTime', fieldType: 'RANGE_DATE' },
  { fieldLabel: '过磅时间', fieldName: 'weightTime', fieldType: 'RANGE_DATETIME_FREE' },
  { fieldLabel: '一检时间', fieldName: 'firstCheckTime', fieldType: 'RANGE_DATETIME' },
  { fieldLabel: '更新时间', fieldName: 'updateTime', fieldType: 'DATETIME' }
]);

interface TableColumnsConfigItem {
  /** 表格列名 */
  fieldLabel: string;
  /** 字段名称 */
  fieldName: string;
  /** 列宽度 */
  width?: number;
  /**
   * 字段格式化函数
   * @param row 当前行数据
   * @param column 当前列数据
   * @param cellValue 当前单元格数据
   * @param index 当前行索引
   */
  format?: Function;
  /**
   * 字段固定模式。
   *
   * - movable: 可拖动 (默认)
   * - left: 固定在左侧
   * - right: 固定在右侧
   */
  fixMode?: 'movable' | 'left' | 'right';
  [key: string]: unknown;
}
// 表格显示字段配置项
const tableColumnsConfigInit = ref<TableColumnsConfigItem[]>([
  { fieldLabel: '司机姓名', fieldName: 'driverName', fixMode: 'left' },
  { fieldLabel: '司机手机号', fieldName: 'driverPhone', width: 160, fixMode: 'left' },
  { fieldLabel: '车牌号', fieldName: 'carNumber' },
  { fieldLabel: '需求车型', fieldName: 'carType' },
  {
    fieldLabel: '是否计量',
    fieldName: 'isMeasure',
    format: (row: Record<string, unknown>) => (row.isMeasure ? '是' : '否')
  },
  { fieldLabel: '进厂日期', fieldName: 'inDate', width: 120 },
  { fieldLabel: '出厂日期', fieldName: 'outDate', width: 120 },
  { fieldLabel: '创建时间', fieldName: 'createTime', width: 180 },
  { fieldLabel: '过磅时间', fieldName: 'weightTime', width: 180 },
  { fieldLabel: '更新时间', fieldName: 'updateTime', width: 180 },
  { fieldLabel: '状态', fieldName: 'vehicleStatus', width: 120, fixMode: 'right' }
]);

// 是否缓存列表宽度，默认缓存
const isCacheTableColumnsWidth = ref<boolean>(true);

/**
 * 查询区布局配置项，free为自由布局，shrink为"展开收起"布局
 * 注意：如果希望查询区布局保持不变，需要先设置自动布局模式(isOpenQueryAreaAutoShow)为false
 * 否则这个值会在运行时中发生变化，设置是没有效果的
 */
const queryAreaShowMode = ref<'free' | 'shrink'>('shrink');
// 是否开启自动布局模式，开启后会根据查询区条件的多少，自动在free布局和shrink布局中切换
const isOpenQueryAreaAutoShow = ref<boolean>(true);
// 辅助函数：用于判断一个flex布局的元素内部是否发生换行
const elementHasWrapped = (container: Element | null): boolean => {
  if (!container || container.children.length <= 1) return false;
  const { top: firstChildTop } = container.children[0].getBoundingClientRect();
  return Array.from(container.children)
    .slice(1)
    .some((item) => Math.abs(item.getBoundingClientRect().top - firstChildTop) > 1);
};
// 开启自动布局模式的情况下，计算查询区布局
const computeQueryArea = () => {
  if (!isOpenQueryAreaAutoShow.value) return;
  const hasWrapped = elementHasWrapped(queryAreaFormRef.value?.$el as Element);
  if (hasWrapped) {
    queryAreaShowMode.value = 'shrink';
  } else {
    queryAreaShowMode.value = 'free';
    isShrink.value = true;
  }
};
// 监听窗口大小变化，自动计算查询区布局
window.addEventListener('resize', _.debounce(computeQueryArea, 100));

onMounted(() => {
  reloadPage();
});
/************************************************/
/**************** 参数配置区 结束 ****************/
/************************************************/

/**************************************************/
/**************** 参数初始化区 开始 ****************/
/**************************************************/

// 辅助函数: 用于设置下拉框列表中的数据项fieldOptions
const setFieldOptions = (fieldName: string, options: fieldOptionsItem[]) => {
  const field = queryFormConfigInit.value.find((item) => item.fieldName === fieldName);
  if (
    field &&
    ['SELECT', 'MULTI_SELECT', 'CASCADE_SELECT', 'CASCADE_MULTI_SELECT'].includes(
      field.fieldType as string
    )
  ) {
    field.fieldOptions = options;
  }
};

// 示例代码: 设置某个下拉框列表中的数据项fieldOptions，正式使用时请删除
const carTypeOptions = [
  { label: '叉车', value: '1' },
  { label: '牵引车', value: '2' },
  { label: '自卸车', value: '3' },
  { label: '搅拌车', value: '4' },
  { label: '其他', value: '5' }
];
setFieldOptions('carType', carTypeOptions);

// 树形下拉框
const deliveryAddressOptions = [
  {
    label: '北京市',
    value: '1',
    children: [
      {
        label: '朝阳区',
        value: '101',
        children: [
          { label: '三里屯', value: '10101' },
          { label: '望京', value: '10102' },
          { label: '国贸', value: '10103' }
        ]
      },
      {
        label: '海淀区',
        value: '102',
        children: [
          { label: '中关村', value: '10201' },
          { label: '五道口', value: '10202' },
          { label: '清华园', value: '10203' }
        ]
      }
    ]
  },
  {
    label: '上海市',
    value: '2',
    children: [
      {
        label: '浦东新区',
        value: '201',
        children: [
          { label: '陆家嘴', value: '20101' },
          { label: '张江', value: '20102' },
          { label: '金桥', value: '20103' }
        ]
      },
      {
        label: '徐汇区',
        value: '202',
        children: [
          { label: '徐家汇', value: '20201' },
          { label: '衡山路', value: '20202' },
          { label: '漕河泾', value: '20203' }
        ]
      }
    ]
  },
  {
    label: '广州市',
    value: '3',
    children: [
      {
        label: '天河区',
        value: '301',
        children: [
          { label: '珠江新城', value: '30101' },
          { label: '体育中心', value: '30102' },
          { label: '天河北', value: '30103' }
        ]
      },
      {
        label: '越秀区',
        value: '302',
        children: [
          { label: '北京路', value: '30201' },
          { label: '上下九', value: '30202' },
          { label: '沙面', value: '30203' }
        ]
      }
    ]
  },
  {
    label: '深圳市',
    value: '4',
    children: [
      {
        label: '南山区',
        value: '401',
        children: [
          { label: '科技园', value: '40101' },
          { label: '蛇口', value: '40102' },
          { label: '前海', value: '40103' }
        ]
      },
      {
        label: '福田区',
        value: '402',
        children: [
          { label: '华强北', value: '40201' },
          { label: '车公庙', value: '40202' },
          { label: '福田中心', value: '40203' }
        ]
      }
    ]
  },
  {
    label: '成都市',
    value: '5',
    children: [
      {
        label: '锦江区',
        value: '501',
        children: [
          { label: '春熙路', value: '50101' },
          { label: '太古里', value: '50102' },
          { label: '东大街', value: '50103' }
        ]
      },
      {
        label: '武侯区',
        value: '502',
        children: [
          { label: '科华北路', value: '50201' },
          { label: '红牌楼', value: '50202' },
          { label: '玉林', value: '50203' }
        ]
      }
    ]
  }
];
setFieldOptions('deliveryAddress', deliveryAddressOptions);

// 从查询区配置项queryFormConfig中获取查询表单的初始值
const queryForm = reactive<Record<string, unknown>>({});
// 辅助函数: 用于获取查询表单的初始值
const getDefaultValue = (item: QueryFormConfigItem) => {
  if (!item.valueType && !item.fieldType) {
    return '';
  }
  const formatMap = {
    RANGE_DATE: 'YYYY-MM-DD',
    RANGE_DATETIME: 'YYYY-MM-DD HH:mm'
  };
  switch (item.valueType) {
    case 'ARRAY':
      return [];
    case 'NUMBER':
    case 'DATE':
      return null;
    case 'STRING':
      return '';
    default:
      if (item.fieldType && item.fieldType in formatMap) {
        return [
          dayjs()
            .subtract(60, 'day')
            .format(formatMap[item.fieldType as keyof typeof formatMap]),
          dayjs().format(formatMap[item.fieldType as keyof typeof formatMap])
        ];
      }
      return null;
  }
};
// 重置查询表单
const getQueryForm = () => {
  queryFormConfigInit.value.forEach((item) => {
    // console.log(item, getDefaultValue(item));
    queryForm[item.fieldName] = getDefaultValue(item);
  });
  return queryForm;
};
getQueryForm();

/**************************************************/
/**************** 参数初始化区 结束 ****************/
/**************************************************/

/***************************************************/
/**************** 时间选择器定义 开始 ****************/
/***************************************************/

const firstSelectedDateRef = ref<Date | null>(null);
// 用于记录首个日期时间范围选择器的值，从而限制第二个日期时间范围选择器的可选范围
const onCalendarChange = (dateRange: Date[]) => {
  const [minDate, maxDate] = dateRange;
  if (minDate && !maxDate) {
    firstSelectedDateRef.value = minDate;
  } else {
    firstSelectedDateRef.value = null;
  }
  // 保证在改选日期之后仍然保持年月日输入框禁用
  nextTick(() => {
    const timePickerInnerInputs = document.querySelectorAll(
      '.limited-picker .el-date-range-picker__time-picker-wrap:nth-child(1) input'
    );
    for (const el of timePickerInnerInputs) {
      (el as HTMLInputElement).disabled = true;
    }
  });
};
const createDisabledDate = (durationDays: number = 60, containsToday: boolean = true) => {
  return function (time: Date) {
    const now = dayjs();
    let isFutureDate = dayjs(time).isAfter(now);
    if (!containsToday) {
      isFutureDate = dayjs(time).isAfter(now.subtract(1, 'day'));
    }
    const firstSelectedDay = firstSelectedDateRef.value;
    if (!firstSelectedDay) {
      return isFutureDate;
    } else {
      const selectedDay = dayjs(firstSelectedDay);
      const isOutOfDuration =
        dayjs(time).isBefore(selectedDay.subtract(durationDays, 'day')) ||
        dayjs(time).isAfter(selectedDay.add(durationDays, 'day'));
      return isFutureDate || isOutOfDuration;
    }
  };
};
// 日期时间范围选择器的不可选日期
const disabledDate = createDisabledDate();
// 导出框内的时间范围选择器的不可选日期
const disabledDateForExport = createDisabledDate(365);
// 设置日期时间选择器下拉框中，上方的日期输入框不可选，从而防止用户手动输入日期，导致选择的日期范围不符合要求
const onVisibleChange = (val: boolean) => {
  if (val) {
    firstSelectedDateRef.value = null;
    const timePickerInnerInputs = document.querySelectorAll(
      '.limited-picker .el-date-range-picker__time-picker-wrap:nth-child(1) input'
    );
    for (const el of timePickerInnerInputs) {
      (el as HTMLInputElement).disabled = true;
    }
  }
};

/***************************************************/
/**************** 时间选择器定义 结束 ****************/
/***************************************************/

// 该页面的本地存储的key值，用于存储页面的配置项。注意！每个页面的localForageKey取值必须唯一。
const localForageKey = ref<string>(`${projectName}-${String(route.name)}-${route.path}`);
// 页面的配置项类型
type PageConfig = {
  queryFormOrder: Record<string, number>;
  queryFormFilter: Record<string, number>;
  tableColumnsOrder: Record<string, number>;
  tableColumnsFilter: Record<string, number>;
  tableColumnsWidth?: Record<string, number>;
};

// 检查indexedDB中的页面配置项是否正确，如果不正确，则将其清空
const verifyPageConfig = async () => {
  const res: PageConfig | null = await localForage.getItem(localForageKey.value);
  const queryFormOrder = res?.queryFormOrder;
  const tableColumnsOrder = res?.tableColumnsOrder;

  // 获取之前缓存配置项的键值，即需要参与配置的字段名集合
  const computedQueryOrder = queryFormOrder ? Object.keys(queryFormOrder) : [];
  const computedTableColumnOrder = tableColumnsOrder ? Object.keys(tableColumnsOrder) : [];

  // 计算目前的配置项顺序
  const nowQueryOrder = queryFormConfigInit.value
    .filter((item) => item.fixMode !== 'left' && item.fixMode !== 'right')
    .map((item) => item.fieldName);
  const nowTableColumnOrder = tableColumnsConfigInit.value
    .filter((item) => item.fixMode !== 'left' && item.fixMode !== 'right')
    .map((item) => item.fieldName);

  // 如果indexedDB中的配置项和目前的配置项不一致，则将indexedDB中的配置项清空
  if (
    _.difference(computedQueryOrder, nowQueryOrder).length ||
    _.difference(computedTableColumnOrder, nowTableColumnOrder).length ||
    _.difference(nowQueryOrder, computedQueryOrder).length ||
    _.difference(nowTableColumnOrder, computedTableColumnOrder).length
  ) {
    await localForage.removeItem(localForageKey.value);
  }
};

const reloadPage = async () => {
  await getFieldOrderAndFilter();
  computeQueryArea();
  onReset();
};

// 查询区和列表区的抽屉区域模板引用
const sortableDrawerQuery = ref<HTMLElement | null>();
const sortableDrawerTable = ref<HTMLElement | null>();

// 查询区配置项的显示顺序
let queryFormConfigOrder: Record<string, number> = {};
// 查询区配置项是否显示
let queryFormConfigFilter: Record<string, number> = {};
// 查询区配置项，用于最终对查询区进行渲染
const queryFormConfig = ref<QueryFormConfigItem[]>([]);
// 查询区配置项的抽屉配置项
const queryFormConfigDrawer = ref<Pick<QueryFormConfigItem, 'fieldName' | 'fieldLabel'>[]>([]);
// 查询区配置项的抽屉配置项: 固定在左侧
const queryFormConfigDrawerFixedLeft = ref<Pick<QueryFormConfigItem, 'fieldName' | 'fieldLabel'>[]>(
  []
);
// 查询区配置项的抽屉配置项: 固定在右侧
const queryFormConfigDrawerFixedRight = ref<
  Pick<QueryFormConfigItem, 'fieldName' | 'fieldLabel'>[]
>([]);
const queryFormConfigFilterDrawer = ref<Record<string, boolean>>({});

// 列表区配置项的显示顺序
let tableColumnsConfigOrder: Record<string, number> = {};
// 列表区配置项是否显示
let tableColumnsConfigFilter: Record<string, number> = {};
// 列表区配置项，用于最终对列表区进行渲染
const tableColumnsConfig = ref<TableColumnsConfigItem[]>([]);
// 列表区配置项的抽屉配置项
const tableColumnsConfigDrawer = ref<Pick<TableColumnsConfigItem, 'fieldName' | 'fieldLabel'>[]>(
  []
);
// 列表区配置项的抽屉配置项: 固定在左侧
const tableColumnsConfigDrawerFixedLeft = ref<
  Pick<TableColumnsConfigItem, 'fieldName' | 'fieldLabel'>[]
>([]);
// 列表区配置项的抽屉配置项: 固定在右侧
const tableColumnsConfigDrawerFixedRight = ref<
  Pick<TableColumnsConfigItem, 'fieldName' | 'fieldLabel'>[]
>([]);
const tableColumnsConfigFilterDrawer = ref<Record<string, boolean>>({});

// 计算查询区和列表区实际渲染的配置项: 辅助计算函数
const computeConfig = (
  initConfig: QueryFormConfigItem[] | TableColumnsConfigItem[],
  orderConfig: Record<string, number>,
  filterConfig: Record<string, number>
) => {
  const fixedLeft = initConfig.filter((item) => item.fixMode === 'left');
  const fixedRight = initConfig.filter((item) => item.fixMode === 'right');
  const movable = initConfig
    .filter((item) => item.fixMode !== 'left' && item.fixMode !== 'right')
    .sort((a, b) => orderConfig[a.fieldName] - orderConfig[b.fieldName])
    .filter((item) => filterConfig[item.fieldName] === 1);

  return [...fixedLeft, ...movable, ...fixedRight];
};
// 计算查询区和列表区实际渲染的配置项: 主函数
const computeFieldConfig = () => {
  queryFormConfig.value = computeConfig(
    queryFormConfigInit.value,
    queryFormConfigOrder,
    queryFormConfigFilter
  );
  tableColumnsConfig.value = computeConfig(
    tableColumnsConfigInit.value,
    tableColumnsConfigOrder,
    tableColumnsConfigFilter
  );
};
// 从indexedDB中获取查询区和列表区配置项的显示顺序和是否显示，以及根据用户自定义的列宽配置设置列宽
const getFieldOrderAndFilter = async () => {
  // 检查indexedDB中的页面配置项是否正确，如果不正确，则将其清空
  await verifyPageConfig();
  const res: PageConfig | null = await localForage.getItem(localForageKey.value);
  let shouldSetItem: boolean = false;
  const CurdStandardPage = (res || {}) as PageConfig;

  if (res && 'queryFormOrder' in res) {
    queryFormConfigOrder = res.queryFormOrder;
  } else {
    queryFormConfigInit.value
      .filter((item) => item.fixMode !== 'left' && item.fixMode !== 'right')
      .forEach((item, index) => {
        queryFormConfigOrder[item.fieldName] = index;
      });
    // 存入CurdStandardPage中的queryFormOrder配置项里
    CurdStandardPage.queryFormOrder = queryFormConfigOrder;
    shouldSetItem = true;
  }
  if (res && 'queryFormFilter' in res) {
    queryFormConfigFilter = res.queryFormFilter;
  } else {
    queryFormConfigInit.value
      .filter((item) => item.fixMode !== 'left' && item.fixMode !== 'right')
      .forEach((item) => {
        queryFormConfigFilter[item.fieldName] = 1;
      });
    // 存入CurdStandardPage中的queryFormFilter配置项里
    CurdStandardPage.queryFormFilter = queryFormConfigFilter;
    shouldSetItem = true;
  }
  if (res && 'tableColumnsOrder' in res) {
    tableColumnsConfigOrder = res.tableColumnsOrder;
  } else {
    tableColumnsConfigInit.value
      .filter((item) => item.fixMode !== 'left' && item.fixMode !== 'right')
      .forEach((item, index) => {
        tableColumnsConfigOrder[item.fieldName] = index;
      });
    // 存入CurdStandardPage中的tableColumnsOrder配置项里
    CurdStandardPage.tableColumnsOrder = tableColumnsConfigOrder;
    shouldSetItem = true;
  }
  if (res && 'tableColumnsFilter' in res) {
    tableColumnsConfigFilter = res.tableColumnsFilter;
  } else {
    tableColumnsConfigInit.value
      .filter((item) => item.fixMode !== 'left' && item.fixMode !== 'right')
      .forEach((item) => {
        tableColumnsConfigFilter[item.fieldName] = 1;
      });
    // 存入CurdStandardPage中的tableColumnsFilter配置项里
    CurdStandardPage.tableColumnsFilter = tableColumnsConfigFilter;
    shouldSetItem = true;
  }
  // 处理表格列宽配置
  if (res && 'tableColumnsWidth' in res) {
    if (isCacheTableColumnsWidth.value) {
      // 如果启用缓存，则应用列宽配置到表格配置中
      tableColumnsConfigInit.value.forEach((item) => {
        if (res.tableColumnsWidth && res.tableColumnsWidth[item.fieldName]) {
          item.width = res.tableColumnsWidth[item.fieldName];
        }
      });
    } else {
      // 如果禁用缓存，则从存储中删除列宽配置
      delete res.tableColumnsWidth;
      await localForage.setItem(localForageKey.value, res);
    }
  }
  if (shouldSetItem) {
    await localForage.setItem(localForageKey.value, CurdStandardPage);
  }
  computeFieldConfig();
};

const isShrink = ref<boolean>(true);
// 表格组件引用
const mainTable = ref<InstanceType<typeof ElTable>>();
// 表格数据
const tableData = ref<Record<string, unknown>[]>([]);
// 表格分页配置项
const tablePaginationConfig = {
  pageSize: 10,
  currentPage: 1,
  total: 0,
  handleSizeChange(value: number) {
    tablePaginationConfig.pageSize = value;
    onQuery();
  },
  handleCurrentChange(value: number) {
    tablePaginationConfig.currentPage = value;
    onQuery();
  }
};
const onQuery = async (options?: 'firstPage') => {
  options === 'firstPage' && (tablePaginationConfig.currentPage = 1);
  isShrink.value = true;
  // TODO: 查询操作
  // console.log(queryForm);
  /**
   * 这里需要给tableData和tablePaginationConfig赋值，参考代码：
   * const res = await API.getDataList(); // 获取后端接口数据
   * tableData.value = res.data.list; // 将数据赋值给表格
   * tablePaginationConfig.total = res.data.total; // 将总条数赋值给分页配置项
   */
};

const onReset = () => {
  getQueryForm();
  tablePaginationConfig.currentPage = 1;
  tablePaginationConfig.pageSize = 10;
  onQuery();
};
const onDelete = (row: Record<string, unknown>) => {
  // TODO: 删除操作
  console.log(row);
};

const onHeaderDragend = async (
  newWidth: number,
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  _oldWidth: number,
  column: any,
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  _event: MouseEvent
) => {
  const columnKey = String(column.rawColumnKey);
  const localPageConfig: PageConfig | null = await localForage.getItem(localForageKey.value);
  if (
    localPageConfig &&
    localPageConfig.tableColumnsWidth &&
    'tableColumnsWidth' in localPageConfig
  ) {
    localPageConfig.tableColumnsWidth[columnKey] = newWidth;
    await localForage.setItem(localForageKey.value, localPageConfig);
  } else {
    const newConfig: PageConfig = {
      queryFormOrder: localPageConfig?.queryFormOrder ?? {},
      queryFormFilter: localPageConfig?.queryFormFilter ?? {},
      tableColumnsOrder: localPageConfig?.tableColumnsOrder ?? {},
      tableColumnsFilter: localPageConfig?.tableColumnsFilter ?? {},
      tableColumnsWidth: {
        [columnKey]: newWidth
      }
    };
    await localForage.setItem(localForageKey.value, newConfig);
  }
};

const dialogVisible = ref<boolean>(false);
const isEdit = ref<boolean>(false);
const openDialog = (_isEdit: boolean = false, row: Record<string, unknown> | null = null) => {
  dialogVisible.value = true;
  isEdit.value = _isEdit;
  // TODO: 新增和编辑逻辑
  row ? console.log(row) : '';
};

const exportDialogVisible = ref<boolean>(false);
// 导出弹窗中的查询条件中，不包含时间范围选择器的值
const queryContentWithoutTime = ref<
  { label: string; name: string; value: unknown; type?: string }[]
>([]);
// 导出弹窗中的查询条件中，时间范围选择器值的集合
const queryContentTime = ref<{ label: string; name: string; value: unknown; type?: string }[]>([]);
// 用于导出接口的查询条件，由于在弹窗中可以继续编辑查询条件，因此需要设置该变量
const queryFormForExport = ref<Record<string, unknown>>({});
const openExportDialog = () => {
  // 复制queryForm的内容到queryFormForExport中
  queryFormForExport.value = _.cloneDeep(queryForm);
  // 清空之前的结果
  queryContentWithoutTime.value = [];
  queryContentTime.value = [];
  // 遍历queryFormConfig.value
  queryFormConfig.value.forEach((item) => {
    // 如果queryForm中对应的属性值为空或为空数组，则跳过这次迭代
    let fieldValue = queryForm[item.fieldName];
    if (
      (!fieldValue && fieldValue !== 0) ||
      (Array.isArray(fieldValue) && fieldValue.length === 0)
    ) {
      return;
    }
    // 如果属性值是下拉框，需要选择其中的label值
    if (item.fieldType === 'SELECT') {
      const fieldOptions = queryFormConfigInit.value.find(
        (i) => i.fieldName === item.fieldName
      )!.fieldOptions;
      fieldValue = fieldOptions?.find((i) => i.value === queryForm[item.fieldName])?.label;
    }
    // 如果属性值是数组，使用", "字符串将元素连接起来
    if (
      Array.isArray(fieldValue) &&
      !['RANGE_DATE', 'RANGE_DATE_FREE', 'RANGE_DATETIME', 'RANGE_DATETIME_FREE'].includes(
        item.fieldType || ''
      )
    ) {
      fieldValue = fieldValue.join(', ');
    }
    // 生成要添加的对象
    const objToAdd = {
      label: item.fieldLabel,
      name: item.fieldName,
      value: fieldValue,
      type: item.fieldType
    };
    // 根据fieldType的值将数据分类到queryContentWithoutTime和queryContentTime
    if (
      ['RANGE_DATE', 'RANGE_DATE_FREE', 'RANGE_DATETIME', 'RANGE_DATETIME_FREE'].includes(
        item.fieldType || ''
      )
    ) {
      queryContentTime.value.push(objToAdd);
    } else {
      queryContentWithoutTime.value.push(objToAdd);
    }
  });
  exportDialogVisible.value = true;
};
const clearQueryWithoutTime = () => {
  queryFormConfigInit.value.forEach((item) => {
    if (
      ['RANGE_DATE', 'RANGE_DATE_FREE', 'RANGE_DATETIME', 'RANGE_DATETIME_FREE'].includes(
        item.fieldType || ''
      )
    ) {
      return;
    }
    if (item.valueType === 'ARRAY') {
      queryFormForExport.value[item.fieldName] = [];
    } else if (!item.valueType || item.valueType === 'STRING') {
      queryFormForExport.value[item.fieldName] = '';
    } else if (item.value === 'NUMBER' || item.valueType === 'DATE') {
      queryFormForExport.value[item.fieldName] = null;
    } else {
      queryFormForExport.value[item.fieldName] = null;
    }
  });
  queryContentWithoutTime.value = [];
};
const deleteTimeItem = (fieldName: string) => {
  queryFormForExport.value[fieldName] = [];
  queryContentTime.value = queryContentTime.value.filter((item) => item.name !== fieldName);
};

/**
 * 导出方式一共有两种
 * backend: 利用后端接口进行导出，此时弹出窗口，进行一系列查询参数填写后再传给后端处理
 * immediately：前端直接导出数据
 */
// TODO: 设定导出方式，默认是后端导出，前端导出需要修改
const exportType = ref<'backend' | 'immediately'>('backend');
const onExportImmediately = (name: string = pageTitleName) => {
  const tableComponent = mainTable?.value?.$el;
  if (!tableComponent) {
    ElMessage.error('表格组件未加载，无法导出');
    return;
  }
  const wb = XLSX.utils.table_to_book(tableComponent);
  const fileName = `${name}${dayjs().format('YYYY-MM-DD_HH-mm-ss')}`;
  XLSX.writeFile(wb, fileName + '.xlsx');
};
const onExport = () => {
  // TODO: 导出逻辑，一般情况是向后端接口传查询条件
  console.log(queryFormForExport.value);
  // 在条件传输给后端之后，需要将导出弹窗关闭，并打开"数据处理中"弹窗
  exportDialogVisible.value = false;
  exportConfirmedDialogVisible.value = true;
  remainingSeconds.value = 10;
  startTimer();
};
const exportConfirmedDialogVisible = ref<boolean>(false);
// 跳转到导出页面
const moveToExportPage = () => {
  // TODO: 跳转到导出页面
  const exportPathName = '/';
  router.push({ path: exportPathName });
  return;
};
// "数据处理中"弹窗剩余描述
const remainingSeconds = ref<number>(10);
// 计时器
const exportDialogTimer = ref<number | null>(null);
const startTimer = () => {
  exportDialogTimer.value = setInterval(() => {
    if (remainingSeconds.value > 1) {
      remainingSeconds.value--;
    } else {
      exportConfirmedDialogVisible.value = false;
      clearTimer();
    }
  }, 1000);
};
const clearTimer = () => {
  if (exportDialogTimer.value) {
    clearInterval(exportDialogTimer.value);
    exportDialogTimer.value = null;
  }
};

const drawerVisible = ref<boolean>(false);
watch(drawerVisible, (newVal) => {
  if (newVal) {
    nextTick(() => {
      new Sortable(sortableDrawerQuery.value!, {
        animation: 150,
        onEnd: (evt: SortableEvent) => {
          if (evt.oldIndex === undefined || evt.newIndex === undefined) return;
          const itemMoved = queryFormConfigDrawer.value.splice(evt.oldIndex, 1)[0];
          queryFormConfigDrawer.value.splice(evt.newIndex, 0, itemMoved);
        }
      });
      new Sortable(sortableDrawerTable.value!, {
        animation: 150,
        onEnd: (evt: SortableEvent) => {
          if (evt.oldIndex === undefined || evt.newIndex === undefined) return;
          const itemMoved = tableColumnsConfigDrawer.value.splice(evt.oldIndex, 1)[0];
          tableColumnsConfigDrawer.value.splice(evt.newIndex, 0, itemMoved);
        }
      });
    });
  }
});

// 表格头部功能区配置1
const isHovering = ref<string>('');
const isFullScreen = ref<boolean>(false);
const tableArea = ref<HTMLElement | null>(null);
const tableHeaderConfigs = reactive([
  {
    label: '刷新',
    icon: 'Refresh',
    click: () => {
      onQuery();
    }
  },
  {
    label: '导出',
    icon: 'Download',
    click: () => {
      if (exportType.value === 'immediately') {
        onExportImmediately();
      } else {
        openExportDialog();
      }
    }
  },
  {
    label: '全屏',
    icon: 'FullScreen',
    click: () => {
      const element = tableArea.value;
      if (!isFullScreen.value) {
        isFullScreen.value = true;
        element?.classList.add('p-5', 'overflow-y-auto');
        element?.requestFullscreen();
      } else {
        document.exitFullscreen();
        if (element?.classList.contains('p-5')) {
          element?.classList.remove('p-5', 'overflow-y-auto');
        }
      }
    }
  },
  {
    label: '设置',
    icon: 'Setting',
    click: async () => {
      // 从indexedDB中获取页面配置项
      const config = (await localForage.getItem(localForageKey.value)) as PageConfig | null;
      const configOrderQuery = config?.queryFormOrder || {};
      const configFilterQuery = config?.queryFormFilter || {};
      const configOrderTable = config?.tableColumnsOrder || {};
      const configFilterTable = config?.tableColumnsFilter || {};
      // 将页面配置项赋值到抽屉组件的配置项中
      queryFormConfigInit.value
        .filter((item) => item.fixMode !== 'left' && item.fixMode !== 'right')
        .forEach((item) => {
          queryFormConfigDrawer.value[configOrderQuery[item.fieldName]] = item;
          queryFormConfigFilterDrawer.value[item.fieldName] = !!configFilterQuery[item.fieldName];
        });
      queryFormConfigDrawerFixedLeft.value = queryFormConfigInit.value.filter(
        (item) => item.fixMode === 'left'
      );
      queryFormConfigDrawerFixedRight.value = queryFormConfigInit.value.filter(
        (item) => item.fixMode === 'right'
      );

      tableColumnsConfigInit.value
        .filter((item) => item.fixMode !== 'left' && item.fixMode !== 'right')
        .forEach((item) => {
          tableColumnsConfigDrawer.value[configOrderTable[item.fieldName]] = item;
          tableColumnsConfigFilterDrawer.value[item.fieldName] =
            !!configFilterTable[item.fieldName];
        });
      tableColumnsConfigDrawerFixedLeft.value = tableColumnsConfigInit.value.filter(
        (item) => item.fixMode === 'left'
      );
      tableColumnsConfigDrawerFixedRight.value = tableColumnsConfigInit.value.filter(
        (item) => item.fixMode === 'right'
      );
      handleCheckedFieldChange();
      handleCheckedFieldChangeTable();
      drawerVisible.value = true;
    }
  }
]);

// 当执行exitFullscreen时，isFullScreen设为false
document.addEventListener('fullscreenchange', () => {
  const element = tableArea.value;
  if (!document.fullscreenElement) {
    isFullScreen.value = false;
    if (element?.classList.contains('p-5')) {
      element?.classList.remove('p-5');
    }
    if (element?.classList.contains('overflow-y-auto')) {
      element?.classList.remove('overflow-y-auto');
    }
  }
});

// 抽屉查询区选择和拖拽逻辑
const queryCheckAll = ref<boolean>(false);
const isIndeterminateQuery = ref<boolean>(false);
const handleCheckAllChangeQuery = (val: boolean) => {
  if (val) {
    Object.keys(queryFormConfigFilterDrawer.value).forEach((item) => {
      queryFormConfigFilterDrawer.value[item] = true;
    });
  } else {
    Object.keys(queryFormConfigFilterDrawer.value).forEach((item) => {
      queryFormConfigFilterDrawer.value[item] = false;
    });
  }
  isIndeterminateQuery.value = false;
};

// 抽屉列表区选择和拖拽逻辑
const tableCheckAll = ref<boolean>(false);
const isIndeterminateTable = ref<boolean>(false);
const handleCheckAllChangeTable = (val: boolean) => {
  if (val) {
    Object.keys(tableColumnsConfigFilterDrawer.value).forEach((item) => {
      tableColumnsConfigFilterDrawer.value[item] = true;
    });
  } else {
    Object.keys(tableColumnsConfigFilterDrawer.value).forEach((item) => {
      tableColumnsConfigFilterDrawer.value[item] = false;
    });
  }
  isIndeterminateTable.value = false;
};

const handleCheckedFieldChange = () => {
  let checkedCount = 0;
  Object.keys(queryFormConfigFilterDrawer.value).forEach((item) => {
    queryFormConfigFilterDrawer.value[item] ? checkedCount++ : '';
  });
  const totalCount = Object.keys(queryFormConfigFilterDrawer.value).length;
  queryCheckAll.value = checkedCount === totalCount;
  isIndeterminateQuery.value = checkedCount > 0 && checkedCount < totalCount;
};
const changeOrderQuery = (index: number, type: 'up' | 'down') => {
  if (type === 'up') {
    if (index === 0) return;
    const temp = queryFormConfigDrawer.value[index];
    queryFormConfigDrawer.value[index] = queryFormConfigDrawer.value[index - 1];
    queryFormConfigDrawer.value[index - 1] = temp;
  } else {
    if (index === queryFormConfigDrawer.value.length - 1) return;
    const temp = queryFormConfigDrawer.value[index];
    queryFormConfigDrawer.value[index] = queryFormConfigDrawer.value[index + 1];
    queryFormConfigDrawer.value[index + 1] = temp;
  }
};

const handleCheckedFieldChangeTable = () => {
  let checkedCount = 0;
  Object.keys(tableColumnsConfigFilterDrawer.value).forEach((item) => {
    tableColumnsConfigFilterDrawer.value[item] ? checkedCount++ : '';
  });
  const totalCount = Object.keys(tableColumnsConfigFilterDrawer.value).length;
  tableCheckAll.value = checkedCount === totalCount;
  isIndeterminateTable.value = checkedCount > 0 && checkedCount < totalCount;
};
const changeOrderTable = (index: number, type: 'up' | 'down') => {
  if (type === 'up') {
    if (index === 0) return;
    const temp = tableColumnsConfigDrawer.value[index];
    tableColumnsConfigDrawer.value[index] = tableColumnsConfigDrawer.value[index - 1];
    tableColumnsConfigDrawer.value[index - 1] = temp;
  } else {
    if (index === tableColumnsConfigDrawer.value.length - 1) return;
    const temp = tableColumnsConfigDrawer.value[index];
    tableColumnsConfigDrawer.value[index] = tableColumnsConfigDrawer.value[index + 1];
    tableColumnsConfigDrawer.value[index + 1] = temp;
  }
};

// 关闭右侧抽屉
const handleDrawerClose = () => {
  drawerAreaType.value = '查询区';
  rightDrawer.value?.handleClose();
};
// 保存右侧抽屉的配置项
const saveDrawerData = async () => {
  const CurdStandardPage = ((await localForage.getItem(localForageKey.value)) as PageConfig) || {};
  let fieldOrder: Record<string, number> = {};
  let fieldFilter: Record<string, number> = {};
  let fieldOrderTable: Record<string, number> = {};
  let fieldFilterTable: Record<string, number> = {};

  queryFormConfigDrawer.value.forEach((item, index) => {
    fieldOrder[item.fieldName] = index;
  });
  Object.keys(queryFormConfigFilterDrawer.value).forEach((item) => {
    fieldFilter[item] = queryFormConfigFilterDrawer.value[item] ? 1 : 0;
  });
  tableColumnsConfigDrawer.value.forEach((item, index) => {
    fieldOrderTable[item.fieldName] = index;
  });
  Object.keys(tableColumnsConfigFilterDrawer.value).forEach((item) => {
    fieldFilterTable[item] = tableColumnsConfigFilterDrawer.value[item] ? 1 : 0;
  });

  CurdStandardPage.queryFormOrder = fieldOrder;
  CurdStandardPage.queryFormFilter = fieldFilter;
  CurdStandardPage.tableColumnsOrder = fieldOrderTable;
  CurdStandardPage.tableColumnsFilter = fieldFilterTable;

  await localForage.setItem(localForageKey.value, CurdStandardPage);
  handleDrawerClose();
  await reloadPage();
};

// 右侧抽屉弹窗配置项
const drawerAreaType = ref<string>('查询区');
</script>

<template>
  <div class="overflow-y-auto h-full bg-white">
    <div class="p-5 h-full">
      <!-- 页面标题 -->
      <div class="pb-2.5 mb-4 text-xl font-bold border-b">标准查询页面模板</div>
      <!-- 页面查询区域 -->
      <div
        class="relative -mx-5 mb-4"
        :class="{
          'overflow-hidden': isShrink,
          'h-16': queryAreaShowMode === 'shrink'
        }"
      >
        <div
          class="flex justify-between w-full bg-white"
          :class="{ 'shadow-bottom': !isShrink, 'absolute z-10': queryAreaShowMode === 'shrink' }"
        >
          <!-- 查询表单 -->
          <div class="flex-1 pl-5">
            <el-form ref="queryAreaFormRef" :model="queryForm" inline label-position="top">
              <el-form-item
                v-for="(item, index) in queryFormConfig"
                :key="index"
                class="w-60"
                :label="item.fieldLabel"
              >
                <!-- 普通输入框 -->
                <template v-if="!item.fieldType || item.fieldType === 'INPUT'">
                  <el-input
                    class="-mt-1 w-full"
                    v-model.trim="queryForm[item.fieldName]"
                    placeholder="请输入"
                    clearable
                  />
                </template>
                <!-- 普通下拉框 -->
                <template v-if="item.fieldType === 'SELECT'">
                  <el-select
                    class="-mt-1 w-full"
                    v-model="queryForm[item.fieldName]"
                    placeholder="请选择"
                    filterable
                    clearable
                  >
                    <el-option
                      v-for="(option, index) in item.fieldOptions"
                      :key="index"
                      :label="option.label"
                      :value="option.value"
                    />
                  </el-select>
                </template>
                <!-- 普通多选下拉框 -->
                <template v-if="item.fieldType === 'MULTI_SELECT'">
                  <el-select
                    class="-mt-1 w-full"
                    v-model="queryForm[item.fieldName]"
                    placeholder="请选择"
                    filterable
                    clearable
                    multiple
                    collapse-tags
                    collapse-tags-tooltip
                  >
                    <el-option
                      v-for="(option, index) in item.fieldOptions"
                      :key="index"
                      :label="option.label"
                      :value="option.value"
                    />
                  </el-select>
                </template>
                <!-- 普通级联选择器 -->
                <template v-if="item.fieldType === 'CASCADE_SELECT'">
                  <el-cascader
                    class="-mt-1 w-full"
                    v-model="queryForm[item.fieldName]"
                    :options="item.fieldOptions"
                    :show-all-levels="false"
                    filterable
                    :props="{ label: 'label', value: 'value', children: 'children' }"
                  />
                </template>
                <!-- 普通多选级联选择器 -->
                <template v-if="item.fieldType === 'CASCADE_MULTI_SELECT'">
                  <el-cascader
                    class="-mt-1 w-full"
                    v-model="queryForm[item.fieldName]"
                    :options="item.fieldOptions"
                    :show-all-levels="false"
                    filterable
                    :props="{
                      label: 'label',
                      value: 'value',
                      children: 'children',
                      multiple: true
                    }"
                    collapse-tags
                    collapse-tags-tooltip
                  />
                </template>
                <!-- 单个日期选择 -->
                <template v-if="item.fieldType === 'DATE'">
                  <el-date-picker
                    class="-mt-1"
                    v-model="queryForm[item.fieldName]"
                    type="date"
                    :prefix-icon="calendarIcon"
                    placeholder="选择日期"
                    value-format="YYYY-MM-DD"
                  />
                </template>
                <!-- 日期范围选择 -->
                <template v-if="item.fieldType === 'RANGE_DATE'">
                  <el-date-picker
                    class="-mt-1"
                    popper-class="limited-picker"
                    v-model="queryForm[item.fieldName]"
                    :clearable="false"
                    :editable="false"
                    type="daterange"
                    :prefix-icon="calendarIcon"
                    range-separator="~"
                    start-placeholder="开始日期"
                    end-placeholder="结束日期"
                    value-format="YYYY-MM-DD"
                    :disabled-date="disabledDate"
                    @calendar-change="onCalendarChange"
                    :default-value="[
                      dayjs().subtract(60, 'day').format('YYYY-MM-DD'),
                      dayjs().format('YYYY-MM-DD')
                    ]"
                  />
                </template>
                <!-- 日期范围选择(无默认值) -->
                <template v-if="item.fieldType === 'RANGE_DATE_FREE'">
                  <el-date-picker
                    class="-mt-1"
                    v-model="queryForm[item.fieldName]"
                    type="daterange"
                    :prefix-icon="calendarIcon"
                    range-separator="~"
                    start-placeholder="开始日期"
                    end-placeholder="结束日期"
                    value-format="YYYY-MM-DD"
                  />
                </template>
                <!-- 单个日期时间选择 -->
                <template v-if="item.fieldType === 'DATETIME'">
                  <el-date-picker
                    class="-mt-1"
                    v-model="queryForm[item.fieldName]"
                    type="datetime"
                    :prefix-icon="clockIcon"
                    placeholder="选择时间"
                    value-format="YYYY-MM-DD HH:mm"
                    format="YYYY-MM-DD HH:mm"
                  />
                </template>
                <!-- 日期时间范围选择 -->
                <template v-if="item.fieldType === 'RANGE_DATETIME'">
                  <el-date-picker
                    class="-mt-1"
                    popper-class="limited-picker"
                    v-model="queryForm[item.fieldName]"
                    :clearable="false"
                    :editable="false"
                    type="datetimerange"
                    :prefix-icon="clockIcon"
                    range-separator="~"
                    start-placeholder="开始时间"
                    end-placeholder="结束时间"
                    value-format="YYYY-MM-DD HH:mm"
                    format="YYYY-MM-DD HH:mm"
                    :disabled-date="disabledDate"
                    :default-value="[
                      dayjs().subtract(60, 'day').format('YYYY-MM-DD HH:mm'),
                      dayjs().format('YYYY-MM-DD HH:mm')
                    ]"
                    :default-time="[new Date(0, 0, 0, 0, 0), new Date(0, 0, 0, 23, 59)]"
                    @calendar-change="onCalendarChange"
                    @visible-change="onVisibleChange"
                  />
                </template>
                <!-- 日期时间范围选择(无默认值) -->
                <template v-if="item.fieldType === 'RANGE_DATETIME_FREE'">
                  <el-date-picker
                    class="-mt-1"
                    v-model="queryForm[item.fieldName]"
                    type="datetimerange"
                    :prefix-icon="clockIcon"
                    range-separator="~"
                    start-placeholder="开始时间"
                    end-placeholder="结束时间"
                    value-format="YYYY-MM-DD HH:mm"
                    format="YYYY-MM-DD HH:mm"
                    :default-time="[new Date(0, 0, 0, 0, 0), new Date(0, 0, 0, 23, 59)]"
                  />
                </template>
              </el-form-item>
            </el-form>
          </div>
          <!-- 表单查询功能区 -->
          <div class="pr-5 w-60 pt-[22px] flex justify-between">
            <!-- 自由布局下的占位元素 -->
            <div v-if="queryAreaShowMode === 'free'"></div>
            <div class="block">
              <el-button type="primary" @click="onQuery('firstPage')">查询</el-button>
              <el-button @click="onReset">重置</el-button>
            </div>
            <div v-if="queryAreaShowMode === 'shrink'" class="block mt-1 mr-4">
              <el-button link @click="isShrink = !isShrink">
                {{ isShrink ? '展开' : '收起' }}
                <el-icon
                  class="ml-1 duration-300 ease-in-out"
                  :style="{
                    transform: isShrink ? 'rotate(180deg)' : 'rotate(0deg)'
                  }"
                  ><ArrowUp />
                </el-icon>
              </el-button>
            </div>
          </div>
        </div>
      </div>
      <!-- 页面列表区域 -->
      <div ref="tableArea" class="block w-full bg-white">
        <!-- 表格头部功能区 -->
        <div class="flex justify-between items-center h-[60px] bg-[#fafafa] border">
          <div>
            <!-- 头部左侧新增按钮 -->
            <el-button type="primary" class="ml-5" @click="openDialog()">
              <el-icon size="18" class="mr-1"><Plus /></el-icon>新增
            </el-button>
          </div>
          <!-- 头部右侧功能按钮 -->
          <div class="flex">
            <el-tooltip
              v-for="(item, index) in tableHeaderConfigs"
              :key="index"
              effect="dark"
              :content="item.label"
              placement="top"
            >
              <template v-if="item.icon === 'FullScreen'">
                <span
                  v-if="!isFullScreen"
                  class="flex justify-center items-center mr-5 w-8 h-8 rounded-full border cursor-pointer"
                  :class="{ 'border-[#697dff] icon-hover': isHovering === item.icon }"
                  @click="item.click"
                  @mouseover="isHovering = item.icon"
                  @mouseleave="isHovering = ''"
                >
                  <el-icon size="18" color="#9d9d9d">
                    <!-- 通过动态组件实现对不同icon的渲染 -->
                    <component :is="item.icon"></component>
                  </el-icon>
                </span>
                <span
                  v-else
                  class="flex justify-center items-center mr-5 w-8 h-8 rounded-full border cursor-pointer"
                  :class="{ 'border-[#697dff] icon-hover': isHovering === item.icon }"
                  @mouseover="isHovering = item.icon"
                  @mouseleave="isHovering = ''"
                >
                  <el-icon size="18" color="#9d9d9d" @click="item.click">
                    <!-- 由于Element Plus没有自带缩小图标，如需更改可自行更改 -->
                    <Close />
                  </el-icon>
                </span>
              </template>
              <span
                v-else
                class="flex justify-center items-center mr-5 w-8 h-8 rounded-full border cursor-pointer"
                :class="{ 'border-[#697dff] icon-hover': isHovering === item.icon }"
                @mouseover="isHovering = item.icon"
                @mouseleave="isHovering = ''"
                @click="item.click"
              >
                <el-icon size="18" color="#9d9d9d">
                  <!-- 通过动态组件实现对不同icon的渲染 -->
                  <component :is="item.icon"></component>
                </el-icon>
              </span>
            </el-tooltip>
          </div>
        </div>
        <!-- 表格 -->
        <el-table
          ref="mainTable"
          :data="tableData"
          border
          stripe
          header-row-class-name="h-14"
          header-cell-class-name="text-[#333]"
          class="w-full"
          @header-dragend="onHeaderDragend"
        >
          <template #empty>
            <div class="flex flex-col items-center py-3">
              <img :src="dataEmpty" alt="暂无数据" class="mx-auto" />
              <span class="pr-3 leading-6 text-center text-gray-400">暂无数据</span>
            </div>
          </template>
          <!-- 序号，可根据实际需要增删 -->
          <el-table-column type="index" center label="序号" fixed="left" width="60" />
          <!-- 表格列配置 -->
          <template v-for="item in tableColumnsConfig" :key="item.fieldName">
            <el-table-column
              :label="item.fieldLabel"
              :prop="item.fieldName"
              :formatter="item.format"
              :fixed="item.fixMode"
              :min-width="item.width ? item.width : 100"
            />
          </template>
          <!-- 操作列，可根据实际需要增删 -->
          <el-table-column fixed="right" label="操作" width="120" class="flex justify-center">
            <template #default="{ row }">
              <el-button text type="primary" class="!p-0" @click="openDialog(true, row)"
                >编辑</el-button
              >
              <el-popconfirm title="确定要删除吗？" @confirm="onDelete(row)">
                <template #reference>
                  <el-button text type="danger" class="!p-0">删除</el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <!-- 表格分页 -->
        <el-pagination
          class="flex justify-end py-5"
          background
          :page-size="tablePaginationConfig.pageSize"
          :current-page="tablePaginationConfig.currentPage"
          :total="tablePaginationConfig.total"
          layout="total, sizes, prev, pager, next, jumper"
          :page-sizes="[10, 20, 40, 60, 80, 100]"
          @size-change="tablePaginationConfig.handleSizeChange"
          @current-change="tablePaginationConfig.handleCurrentChange"
        />
      </div>
    </div>
    <!-- 新增和编辑弹窗 -->
    <el-dialog
      v-model="dialogVisible"
      modal-class="el-dialog-custom"
      :title="isEdit ? '编辑' : '新增'"
      width="30%"
      :close-on-click-modal="false"
    >
      <span>（在这里编写弹窗内容）</span>
      <template #footer>
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
      </template>
    </el-dialog>
    <!-- 导出弹窗 -->
    <el-dialog
      v-model="exportDialogVisible"
      modal-class="el-dialog-custom"
      title="导出确认"
      width="40%"
      :close-on-click-modal="false"
    >
      <div
        class="flex flex-col mx-2.5 py-2 px-5 h-48 border border-[#81d3f8] bg-[#e6f7ff] rounded-lg"
      >
        <div class="font-bold text-black">查询条件预览</div>
        <div class="flex overflow-y-auto flex-wrap flex-1 content-start my-3 export-dialog-custom">
          <div class="mb-1 w-1/2" v-for="item in queryContentWithoutTime" :key="item.label">
            <div class="flex">
              <div class="w-20 text-right">{{ `${item.label}:` }}</div>
              <div class="flex-1 px-2 min-w-0 break-all">{{ item.value }}</div>
            </div>
          </div>
        </div>
        <div class="cursor-pointer text-[#027db4]" @click="clearQueryWithoutTime">清空查询条件</div>
      </div>
      <div class="overflow-y-auto px-2 mx-2.5 mt-4 h-48 export-dialog-custom">
        <div
          v-for="item in queryContentTime"
          :key="item.label"
          class="flex justify-between items-center h-12"
        >
          <div class="flex items-center">
            <div>{{ `${item.label}:` }}</div>
            <template v-if="item.type === 'RANGE_DATETIME'">
              <el-date-picker
                class="!w-[330px] ml-2"
                popper-class="limited-picker"
                v-model="queryFormForExport[item.name]"
                :clearable="false"
                :editable="false"
                type="datetimerange"
                range-separator="~"
                start-placeholder="开始时间"
                end-placeholder="结束时间"
                value-format="YYYY-MM-DD HH:mm"
                format="YYYY-MM-DD HH:mm"
                :disabled-date="disabledDateForExport"
                @calendar-change="onCalendarChange"
                @visible-change="onVisibleChange"
                :default-time="[new Date(0, 0, 0, 0, 0), new Date(0, 0, 0, 23, 59)]"
              />
            </template>
            <template v-if="item.type === 'RANGE_DATETIME_FREE'">
              <el-date-picker
                class="!w-[330px] ml-2"
                popper-class="limited-picker"
                v-model="queryFormForExport[item.name]"
                :clearable="false"
                :editable="false"
                type="datetimerange"
                range-separator="~"
                start-placeholder="开始时间"
                end-placeholder="结束时间"
                value-format="YYYY-MM-DD HH:mm"
                format="YYYY-MM-DD HH:mm"
                :default-time="[new Date(0, 0, 0, 0, 0), new Date(0, 0, 0, 23, 59)]"
              />
            </template>
            <template v-if="item.type === 'RANGE_DATE'">
              <el-date-picker
                class="!w-[330px] ml-2"
                popper-class="limited-picker"
                v-model="queryFormForExport[item.name]"
                :clearable="false"
                :editable="false"
                type="daterange"
                range-separator="~"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                value-format="YYYY-MM-DD"
                :disabled-date="disabledDateForExport"
                @calendar-change="onCalendarChange"
                :default-time="[new Date(0, 0, 0, 0, 0), new Date(0, 0, 0, 23, 59)]"
              />
            </template>
            <template v-if="item.type === 'RANGE_DATE_FREE'">
              <el-date-picker
                class="!w-[330px] ml-2"
                popper-class="limited-picker"
                v-model="queryFormForExport[item.name]"
                :clearable="false"
                :editable="false"
                type="daterange"
                range-separator="~"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                value-format="YYYY-MM-DD"
                :default-time="[new Date(0, 0, 0, 0, 0), new Date(0, 0, 0, 23, 59)]"
              />
            </template>
          </div>
          <div
            v-if="queryContentTime.length > 1"
            class="text-[#d9001b] cursor-pointer select-none"
            @click="deleteTimeItem(item.name)"
          >
            删除
          </div>
        </div>
      </div>
      <template #footer>
        <el-button @click="exportDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="onExport">确 定</el-button>
      </template>
    </el-dialog>
    <!-- 导出-数据处理中弹窗 -->
    <el-dialog
      modal-class="el-dialog-export-confirm-custom"
      v-model="exportConfirmedDialogVisible"
      width="36%"
      :close-on-click-modal="false"
      @closed="clearTimer"
    >
      <div class="flex flex-col items-center">
        <div class="flex items-center mt-8">
          <el-icon size="50" color="#52c41a"><SuccessFilled /></el-icon>
          <div class="ml-3 text-3xl font-bold">数据处理中</div>
        </div>
        <div class="mt-14 text-base">
          点击跳转<span class="text-[#02a7f0] font-bold cursor-pointer" @click="moveToExportPage"
            >历史导出记录</span
          >页面，可下载导出数据
        </div>
        <div class="mt-14 mb-8 text-base text-gray-400">{{ remainingSeconds }}秒后自动关闭弹窗</div>
      </div>
    </el-dialog>
    <!-- 右侧抽屉弹窗 -->
    <el-drawer
      ref="rightDrawer"
      v-model="drawerVisible"
      title="管理展示字段"
      direction="rtl"
      size="30%"
      @closed="handleDrawerClose"
      destroy-on-close
    >
      <el-radio-group v-model="drawerAreaType">
        <el-radio-button label="查询区" />
        <el-radio-button label="列表区" />
      </el-radio-group>
      <div class="py-5 text-sm">
        选中的字段将会在{{ drawerAreaType }}中显示，默认显示所有{{
          drawerAreaType.slice(0, -1)
        }}字段。 点击上移、下移，或直接拖动字段名称可调整字段展示顺序。
      </div>
      <div v-show="drawerAreaType === '查询区'">
        <div class="bg-[#e9ebf0]">
          <div class="flex justify-between p-2.5 border-b border-x">
            <div class="flex items-center">
              <el-checkbox
                v-if="queryFormConfigDrawer.length"
                v-model="queryCheckAll"
                :indeterminate="isIndeterminateQuery"
                @change="handleCheckAllChangeQuery"
              />
              <el-checkbox v-else :model-value="true" disabled />
              <span class="ml-7 text-sm">字段名称</span>
            </div>
            <div class="flex items-center">
              <div class="w-[72px] text-sm">操作</div>
            </div>
          </div>
        </div>
        <div>
          <div
            class="even:bg-[#fafafa]"
            v-for="item in queryFormConfigDrawerFixedLeft"
            :key="item.fieldName"
          >
            <div class="flex justify-between p-2.5 border-b border-x">
              <div class="flex items-center">
                <el-checkbox :model-value="true" disabled />
                <span class="ml-7 text-sm">{{ item.fieldLabel }}</span>
              </div>
            </div>
          </div>
        </div>
        <div ref="sortableDrawerQuery">
          <div
            :class="
              queryFormConfigDrawerFixedLeft.length % 2 === 0
                ? 'even:bg-[#fafafa]'
                : 'odd:bg-[#fafafa]'
            "
            v-for="(item, index) in queryFormConfigDrawer"
            :key="item.fieldName"
          >
            <div class="flex justify-between p-2.5 border-b border-x">
              <div class="flex items-center">
                <el-checkbox
                  v-model="queryFormConfigFilterDrawer[item.fieldName]"
                  @change="handleCheckedFieldChange"
                />
                <span class="ml-7 text-sm">{{ item.fieldLabel }}</span>
              </div>
              <div class="flex justify-between items-center">
                <div
                  class="mr-4 text-sm text-[#697dff] select-none"
                  :class="{
                    'text-[#a8abb2] cursor-not-allowed': index === 0,
                    'cursor-pointer': index !== 0
                  }"
                  @click="changeOrderQuery(index, 'up')"
                >
                  上移
                </div>
                <div
                  class="text-sm text-[#697dff] select-none"
                  :class="{
                    'text-[#a8abb2] cursor-not-allowed': index === queryFormConfigDrawer.length - 1,
                    'cursor-pointer': index !== queryFormConfigDrawer.length - 1
                  }"
                  @click="changeOrderQuery(index, 'down')"
                >
                  下移
                </div>
              </div>
            </div>
          </div>
        </div>
        <div>
          <div
            :class="
              (queryFormConfigDrawerFixedLeft.length + queryFormConfigDrawer.length) % 2 === 0
                ? 'even:bg-[#fafafa]'
                : 'odd:bg-[#fafafa]'
            "
            v-for="item in queryFormConfigDrawerFixedRight"
            :key="item.fieldName"
          >
            <div class="flex justify-between p-2.5 border-b border-x">
              <div class="flex items-center">
                <el-checkbox :model-value="true" disabled />
                <span class="ml-7 text-sm">{{ item.fieldLabel }}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div v-show="drawerAreaType === '列表区'">
        <div class="bg-[#e9ebf0]">
          <div class="flex justify-between p-2.5 border-b border-x">
            <div class="flex items-center">
              <el-checkbox
                v-if="tableColumnsConfigDrawer.length"
                v-model="tableCheckAll"
                :indeterminate="isIndeterminateTable"
                @change="handleCheckAllChangeTable"
              />
              <el-checkbox v-else :model-value="true" disabled />
              <span class="ml-7 text-sm">字段名称</span>
            </div>
            <div class="flex items-center">
              <div class="w-[72px] text-sm">操作</div>
            </div>
          </div>
        </div>
        <div>
          <div
            class="even:bg-[#fafafa]"
            v-for="item in tableColumnsConfigDrawerFixedLeft"
            :key="item.fieldName"
          >
            <div class="flex justify-between p-2.5 border-b border-x">
              <div class="flex items-center">
                <el-checkbox :model-value="true" disabled />
                <span class="ml-7 text-sm">{{ item.fieldLabel }}</span>
              </div>
            </div>
          </div>
        </div>
        <div ref="sortableDrawerTable">
          <div
            :class="
              tableColumnsConfigDrawerFixedLeft.length % 2 === 0
                ? 'even:bg-[#fafafa]'
                : 'odd:bg-[#fafafa]'
            "
            v-for="(item, index) in tableColumnsConfigDrawer"
            :key="item.fieldName"
          >
            <div class="flex justify-between p-2.5 border-b border-x">
              <div class="flex items-center">
                <el-checkbox
                  v-model="tableColumnsConfigFilterDrawer[item.fieldName]"
                  @change="handleCheckedFieldChangeTable"
                />
                <span class="ml-7 text-sm">{{ item.fieldLabel }}</span>
              </div>
              <div class="flex justify-between items-center">
                <div
                  class="mr-4 text-sm text-[#697dff] select-none"
                  :class="{
                    'text-[#a8abb2] cursor-not-allowed': index === 0,
                    'cursor-pointer': index !== 0
                  }"
                  @click="changeOrderTable(index, 'up')"
                >
                  上移
                </div>
                <div
                  class="text-sm text-[#697dff] select-none"
                  :class="{
                    'text-[#a8abb2] cursor-not-allowed':
                      index === tableColumnsConfigDrawer.length - 1,
                    'cursor-pointer': index !== tableColumnsConfigDrawer.length - 1
                  }"
                  @click="changeOrderTable(index, 'down')"
                >
                  下移
                </div>
              </div>
            </div>
          </div>
        </div>
        <div>
          <div
            :class="
              (tableColumnsConfigDrawerFixedLeft.length + tableColumnsConfigDrawer.length) % 2 === 0
                ? 'even:bg-[#fafafa]'
                : 'odd:bg-[#fafafa]'
            "
            v-for="item in tableColumnsConfigDrawerFixedRight"
            :key="item.fieldName"
          >
            <div class="flex justify-between p-2.5 border-b border-x">
              <div class="flex items-center">
                <el-checkbox :model-value="true" disabled />
                <span class="ml-7 text-sm">{{ item.fieldLabel }}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="flex justify-center items-center p-5">
        <el-button @click="handleDrawerClose">取消</el-button>
        <el-button type="primary" @click="saveDrawerData">确定</el-button>
      </div>
    </el-drawer>
  </div>
</template>

<style lang="scss" scoped>
.export-dialog-custom::-webkit-scrollbar {
  width: 10px;
  border-radius: 5px;
  background: rgba(0, 0, 0, 0.1);
}
.export-dialog-custom::-webkit-scrollbar-thumb {
  border-radius: 5px;
  background: rgba(0, 0, 0, 0.2);
}
:global(.icon-hover .el-icon) {
  color: #697dff;
}
:global(.el-drawer__header) {
  border-bottom: 1px solid #ddd;
  color: #222;
  margin: 0;
  padding: 20px;
}
:global(.limited-picker .el-date-range-picker__time-picker-wrap:nth-child(1) .el-input__wrapper) {
  background: #f5f7fa;
  cursor: not-allowed;
}
:global(.limited-picker .el-date-range-picker__time-picker-wrap:nth-child(1) input) {
  color: #a8abb2;
  cursor: not-allowed;
}
:global(.el-dialog-custom .el-dialog) {
  border-radius: 8px;
  box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.3);
}
:global(.el-dialog-custom .el-dialog .el-dialog__header) {
  background: #f2f2f2;
  margin: 0;
  padding: 16px 20px;
  border-radius: 8px 8px 0 0;
}
:global(.el-dialog-custom .el-dialog .el-dialog__footer) {
  padding: 12px 20px;
  border-top: 1px solid #ddd;
}
:global(.el-dialog-export-confirm-custom .el-dialog) {
  border-radius: 8px;
  box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.3);
}
</style>
